import {
	methods, typeState
} from '../constants/index';
import { handleStrRef as filterRef } from './handleSchema';

type Param = Record<string, ParamSpec>;
const applyStateRef = 'state.payload';

export function handleRef (data: any) {
	const fnCall = typeState.get(data.type);
	return fnCall ? fnCall(data.ref) : 'any';
}

/**
 * code example:
 * url: /user/{username}
 * @param state ParamStoreSpec
 * @param schema SchemaContentFace
 */
export function mainStateCompose (state: ParamStoreSpec, schema: SchemaContentFace) {
	let applyRef: string | undefined;
	let parameter: Param | null = {};
	let url = schema.url.replace(/{/g, '${state.');

	if (state.formData?.payload) {
		applyRef = applyStateRef;
		state.formData.payload.ref = 'FormData';
		parameter.payload = state.formData.payload;
	}

	if (state.body?.payload) {
		applyRef = applyStateRef;
		const payload = state.body.payload;
		if (payload.ref) {
			payload.ref = filterRef(payload.ref);
		}
		parameter.payload = payload;
	}
	const compose = Object.assign({}, state.query, state.path);

	for (const key in compose) {
		const payload = compose[key];
		if (payload.ref) {
			payload.ref = filterRef(payload.ref);
		}
		parameter[key] = payload;
	}

	if (methods.includes(schema.method) && state.query) {
		const searchParams: string[] = [];
		const keys = Object.keys(state.query);
		for (const key of keys) {
			searchParams.push(key.concat('=${state.', key, '}'));
		}
		if (searchParams.length > 0) {
			url += '?'.concat(searchParams.join('&'));
		}
	}

	const limits = Object.keys(parameter);
	if (limits.length < 1) parameter = null;

	return {
		type: parameter,
		name: 'state',
		url: url,
		applyRef: applyRef,
	};
}
